#include "StdAfx.h"
#include "AnyView.h"
#include "GraphicDevice.h"
#include "AnyDocument.h"
#include "EditorMgr.h"
#include "RenderEngine.h"
#include "SketchPlane.h"
#include <TDF_Tool.hxx>
#include <gp_Pln.hxx>
#include <gp_Lin.hxx>
CAnyView::CAnyView():
m_hOwnerWnd(NULL),
m_pAnyDoc(NULL)
{
	m_pRender = new CRenderEngine;
	m_pEditorMgr = new CEditorMgr(this);
	m_pSketchPlane = new CSketchPlane(this);
}

CAnyView::~CAnyView(void)
{
	if(!m_OccView)
		m_OccView->Remove();

	delete m_pSketchPlane;
	delete m_pEditorMgr;
	delete m_pRender;
}

bool CAnyView::Initialize(HWND hWnd, CAnyDocument* pAnyDoc)
{
	m_pAnyDoc = pAnyDoc;
	m_hOwnerWnd = hWnd;
	m_pRender->AttachToLabel(GetDocument()->GetRootLabel());

	m_OccView = m_pRender->AttachToWindow(hWnd);

	// set triedron
	//m_OccView->ZBufferTriedronSetup();
	//m_OccView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_SNOW, 0.05,V3d_ZBUFFER);
	m_OccView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER/*Aspect_TOTP_CENTER*/, Quantity_NOC_RED, 0.1);

	m_pSketchPlane->SetLocation(gp_Pnt(0,0,0));
	m_pSketchPlane->SetDirection(gp_Dir(0,0,1));
	m_pSketchPlane->Update();
	return true;
}

void CAnyView::Redraw()
{
	if(!m_OccView.IsNull())
		m_OccView->Redraw();
}

void CAnyView::Resize()
{
	if(!m_OccView.IsNull())
		m_OccView->MustBeResized();
}


CAnyDocument* CAnyView::GetDocument()
{
	return m_pAnyDoc;
}
HWND CAnyView::GetOwnerWnd()const
{
	return m_hOwnerWnd;
}

CEditorMgr* CAnyView::GetEditorMgr(void)
{
	return m_pEditorMgr;
}
CRenderEngine* CAnyView::GetRender()
{
	return m_pRender;
}
void CAnyView::Zoom(long x, long y, long cx, long cy)
{
	m_OccView->Zoom(x, y, cx, cy);
}

void CAnyView::Pan(long x, long y)
{
	m_OccView->Pan(x, y);
}

void CAnyView::StartRotation(long x, long y)
{ 
	m_OccView->StartRotation(x, y);
}

void CAnyView::Rotation(long x, long y)
{
	m_OccView->Rotation(x, y);
}

void CAnyView::SetProj(UINT nProj)
{
	m_OccView->SetProj((V3d_TypeOfOrientation)nProj);
}

void CAnyView::ConvertToGrid(int x, int y, gp_Pnt& point)
{
	V3d_Coordinate X,Y,Z;
	m_OccView->ConvertToGrid(x, y, X, Y, Z);
	point = gp_Pnt(X,Y,Z);
}
namespace
{
	gp_Pnt LineToPlane(const gp_Lin& line, const gp_Pln& plane)
	{
		Standard_Real a,b,c,d;
		plane.Coefficients(a,b,c,d);
		gp_Pnt pt = line.Location();
		gp_Dir nor = line.Direction();
		Standard_Real t = -(a*pt.X() + b*pt.Y() + c*pt.Z() + d)/(a*nor.X()+b*nor.Y()+c*nor.Z());

		gp_Pnt dot;
		dot.SetX(pt.X()+nor.X()*t);
		dot.SetY(pt.Y()+nor.Y()*t);
		dot.SetZ(pt.Z()+nor.Z()*t);

		return dot;
	}

}

void CAnyView::Convert(int x, int y, const gp_Pnt& location, gp_Pnt& point)
{
	V3d_Coordinate X,Y,Z;
	m_OccView->Convert(x,y,X,Y,Z);
	// line
	gp_Pnt ptLine(X,Y,Z);
	m_OccView->Proj(X,Y,Z);
	gp_Dir dirLine(X,Y,Z);
	gp_Lin line(ptLine, dirLine);
	// plane
	gp_Dir dirPlane(-X,-Y,-Z);
	gp_Pnt ptPlane = location;
	gp_Pln plane(ptPlane,dirPlane);

	point = LineToPlane(line, plane);
}

void CAnyView::Convert(int x, int y, const gp_Pln& plane, gp_Pnt& point)
{
	V3d_Coordinate X,Y,Z;
	m_OccView->Convert(x,y,X,Y,Z);
	// line
	gp_Pnt ptLine(X,Y,Z);
	m_OccView->Proj(X,Y,Z);
	gp_Dir dirLine(X,Y,Z);
	gp_Lin line(ptLine, dirLine);

	point = LineToPlane(line, plane);
}

const gp_Dir& CAnyView::CurPlaneNormal()
{
	return m_pSketchPlane->GetDirection();
}

void CAnyView::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	::SendMessage(m_hOwnerWnd, message, wParam, lParam);
}
void CAnyView::UpdatePlane(CSketchPlane* pPlane)
{
	delete m_pSketchPlane;
	m_pSketchPlane = pPlane;
	m_pSketchPlane->Update();

}